package applet.utils;

import java.applet.Applet;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import javax.swing.SwingUtilities;

import kb.DescriptionLogicsKB;

import utils.parser.Parser;
import utils.exception.SyntaxParsingException;

import algebra.ProjectionDescription;
import algebra.op.CQuery;
import algebra.op.InformativeObjectQuery;
import algebra.visitors.QueryVisitorEvaluator;
import app.io.LoadWebFile;

import entities.ConceptAssertion;
import entities.concept.AndConcept;
import entities.concept.Concept;
import entities.concept.ExistsConcept;

public class ParamParser extends Applet{

	private String concept;
	private String pd;
	private Concept parsedC;
	private ProjectionDescription parsedPd;
	private DescriptionLogicsKB kb;
	private int[] kbstat; // # of instances, concept assertions, role assertions, axioms.
	private static boolean TEST = false;
	public void init(){
		try {
            SwingUtilities.invokeAndWait(new Runnable() {
                public void run() {
                	kbstat = new int[4];
                	if(TEST){
                		setParams("Student", "(pd-and (pd-feature name) (pd-feature age) )");
                    	parseParams();
                    	parseTargetKB("http://localhost/system/kb/sample.kbox");
                    	generateAndEvalQuery();
                	}
                	
                }
            });
        } catch (Exception e) {
            System.err.println("Getting paramters failed.");
        }

	}
	
	public int[] getKBStat(){
		return this.kbstat;
	}
	public boolean parseTargetKB(String url){
		//not a query file
		LoadWebFile loader;
		if(TEST){
			loader = new LoadWebFile(url, false);
		}else{
			loader = new LoadWebFile(getCodeBase()+url, false);
		}
		
		boolean getfile = loader.resolveFile();
		if(!getfile){
			//failed to get a file
			return false;
		}
		this.kb = loader.getKB();
		//set stat info
		this.kbstat[0] = this.kb.getAbox().getABoxIndividuals().size();
		this.kbstat[1] = this.kb.getAbox().getNumCA();
		this.kbstat[2] = this.kb.getAbox().getNumRA();
		this.kbstat[3] = this.kb.getTbox().getNumAx();
		return true;
	}
	
	public Concept getParsedConcept(){
		return this.parsedC;
	}
	public ProjectionDescription getParsedPd(){
		return this.parsedPd;
	}
	public void setParams(String C, String PD){
		this.concept = C;
		this.pd = PD;
	}
//	private void getParams() {
//		concept = this.getParameter("C");
//		pd = this.getParameter("PD");
//	}
	
	public boolean parseParams(){
		if(this.concept != null){
			try {
				this.parsedC = Parser.conParser(Parser.getListOfTokensFromTokenizer(this.concept));
			} catch (SyntaxParsingException e) {
				return false;
			}
		}
		if(this.pd != null){
			try {
				this.parsedPd = Parser.createProjectionDescription(Parser.getListOfTokensFromTokenizer(this.pd));
			} catch (SyntaxParsingException e) {
				return false;
			}
		}
		return true;
	}
	
	public String generateAndEvalQuery(){
		InformativeObjectQuery pq = new InformativeObjectQuery(this.parsedPd, new CQuery(this.parsedC));
		QueryVisitorEvaluator eval = new QueryVisitorEvaluator(this.kb);
		List<ConceptAssertion> res = pq.acceptVisitor(eval);
//		/System.out.println(this.kbstat[0]);
		return analyzeResults(res);
	}

	private String analyzeResults(List<ConceptAssertion> res){
		int assertionSize = 20;
		StringBuilder sb = new StringBuilder(res.size()*assertionSize);
//		String mystring ="";
		//sort CAs
		Collections.sort(res, new Comparator<ConceptAssertion>(){
			public int compare(ConceptAssertion o1, ConceptAssertion o2){
				return o1.getIndividual().compareTo(o2.getIndividual());
			}	
		});
		//
		for(int j = 0; j<res.size(); j++){
			ConceptAssertion ca = res.get(j);
			String ret = "<ul STYLE=\"list-style-type:none; font-style: italic;\">"
			+"<img src=\"images/instance.gif\" style=\"vertical-align:middle;\"/> "
			+ "<span style=\" color:"+instancecolor+"\">" 
			+ ca.getIndividual()+"</span> : ";
			Concept c = ca.getConcept();
			ret += analyzeConcept(c) +"</ul>";
			sb.append(ret+"*");
//			mystring += ret+"*";
			if(TEST){
				System.out.println(ret+"\n\n");
			}
		}
		return sb.toString();
	}
	
	private String instancecolor = FontColor.randomDarkRedColorCode();
	private String conceptcolor = FontColor.randomDarkBlueColorCode();
	private String rolecolor = FontColor.randomVioletColorCode();
	//represent a concept in a list form for display
	private String analyzeConcept(Concept C){
//		String s = "";
		StringBuilder sb = new StringBuilder();
		if(C instanceof ExistsConcept){
			ExistsConcept ec = (ExistsConcept) C;
			sb.append("<ul STYLE=\"list-style-type:none\";> "); 
			sb.append("<img src=\"images/exists.gif\" style=\"vertical-align:middle;\"/>");
			sb.append("<span style=\" color:"+rolecolor+"\"> " + ec.getRole()+"</span>");
			sb.append(analyzeConcept(ec.getFiller()) +"</ul>");
		}else if(C instanceof AndConcept){
			AndConcept ac = (AndConcept) C;
			//s += "<ul>";
			List<Concept> sorts = new ArrayList<Concept>(ac.getConceptSet());
			Collections.sort(sorts, new Comparator<Concept>(){
				public int compare(Concept o1, Concept o2){
					return o1.toString().compareTo(o2.toString());
				}	
			});
			//
			for(int i =0; i<sorts.size(); i++){
				sb.append(analyzeConcept(sorts.get(i)));
			}
			//s += "</ul>";
		}else{
			sb.append("<li style = \" margin-left:1em; " );
			sb.append(" color:"+conceptcolor+";\"> ");
			sb.append("<img src=\"images/concept.gif\" style=\"vertical-align:middle;\" /> ");
			sb.append(C.toString()+"</li>");
		}
		return sb.toString();
	}
	
	//determine if the two params can be parsed
	public void start(){
		//this.parseParams();
	}
	
}
